package org.cybzacg.convert.strategy.impl;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionStrategyEnum;
import org.cybzacg.convert.exception.ConversionException;
import org.cybzacg.convert.strategy.ConversionStrategy;

import java.lang.reflect.Array;
import java.util.*;

/**
 * 兼容模式转换策略
 * 最大程度兼容各种类型转换，包括复杂的类型转换场景，实现多级回退机制
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
public class CompatibleConversionStrategy implements ConversionStrategy {

    @Override
    public <T> T execute(
            TypeConverter converter,
            Object source,
            Class<T> targetType,
            T defaultValue,
            ConversionContext context
    ) throws ConversionException {

        // 兼容模式：尝试多种转换方式
        T result = tryMultipleConversions(converter, source, targetType, defaultValue, context);
        
        if (result != null) {
            return result;
        }

        // 如果所有转换方式都失败，返回默认值
        log.debug("所有转换方式都失败，使用默认值: {} -> {}", 
                source, targetType.getSimpleName());
        return defaultValue;
    }

    /**
     * 尝试多种转换方式
     */
    @SuppressWarnings("unchecked")
    private <T> T tryMultipleConversions(
            TypeConverter converter,
            Object source,
            Class<T> targetType,
            T defaultValue,
            ConversionContext context
    ) {
        // 第一级：直接转换
        T result = tryDirectConversion(converter, source, targetType, defaultValue, context);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("直接转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        // 第二级：字符串中转转换
        result = tryStringIntermediateConversion(source, targetType, defaultValue);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("字符串中转转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        // 第三级：数字中转转换
        result = tryNumericIntermediateConversion(source, targetType, defaultValue);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("数字中转转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        // 第四级：集合转换
        result = tryCollectionConversion(source, targetType, defaultValue);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("集合转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        // 第五级：数组转换
        result = tryArrayConversion(source, targetType, defaultValue);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("数组转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        // 第六级：自定义兼容转换
        result = tryCustomCompatibleConversion(source, targetType, defaultValue);
        if (result != null && !isDefaultValue(result, defaultValue)) {
            log.debug("自定义兼容转换成功: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
            return result;
        }

        return null;
    }

    /**
     * 尝试直接转换
     */
    private <T> T tryDirectConversion(
            TypeConverter converter,
            Object source,
            Class<T> targetType,
            T defaultValue,
            ConversionContext context
    ) {
        try {
            return converter.convert(source, targetType, defaultValue, context);
        } catch (Exception e) {
            log.debug("直接转换失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 尝试字符串中转转换
     */
    @SuppressWarnings("unchecked")
    private <T> T tryStringIntermediateConversion(Object source, Class<T> targetType, T defaultValue) {
        try {
            if (source == null) {
                return null;
            }

            // 将源对象转换为字符串
            String strValue = source.toString();
            
            // 从字符串转换为目标类型
            return convertFromString(strValue, targetType, defaultValue);
            
        } catch (Exception e) {
            log.debug("字符串中转转换失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 从字符串转换
     */
    @SuppressWarnings("unchecked")
    private <T> T convertFromString(String strValue, Class<T> targetType, T defaultValue) {
        try {
            if (targetType == String.class) {
                return (T) strValue;
            } else if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf(strValue.trim());
            } else if (targetType == Long.class || targetType == long.class) {
                return (T) Long.valueOf(strValue.trim());
            } else if (targetType == Double.class || targetType == double.class) {
                return (T) Double.valueOf(strValue.trim());
            } else if (targetType == Float.class || targetType == float.class) {
                return (T) Float.valueOf(strValue.trim());
            } else if (targetType == Boolean.class || targetType == boolean.class) {
                return (T) parseBoolean(strValue.trim());
            } else if (targetType == Short.class || targetType == short.class) {
                return (T) Short.valueOf(strValue.trim());
            } else if (targetType == Byte.class || targetType == byte.class) {
                return (T) Byte.valueOf(strValue.trim());
            } else if (targetType == Character.class || targetType == char.class) {
                if (!strValue.isEmpty()) {
                    return (T) Character.valueOf(strValue.charAt(0));
                }
            }
        } catch (Exception e) {
            log.debug("从字符串转换失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 解析布尔值
     */
    private Boolean parseBoolean(String str) {
        String lowerStr = str.toLowerCase();
        if ("true".equals(lowerStr) || "1".equals(lowerStr) || "yes".equals(lowerStr) || 
            "on".equals(lowerStr) || "enabled".equals(lowerStr)) {
            return true;
        } else if ("false".equals(lowerStr) || "0".equals(lowerStr) || "no".equals(lowerStr) || 
                   "off".equals(lowerStr) || "disabled".equals(lowerStr)) {
            return false;
        }
        throw new IllegalArgumentException("无法解析布尔值: " + str);
    }

    /**
     * 尝试数字中转转换
     */
    @SuppressWarnings("unchecked")
    private <T> T tryNumericIntermediateConversion(Object source, Class<T> targetType, T defaultValue) {
        try {
            if (source == null) {
                return null;
            }

            // 尝试将源对象转换为数字
            Double numericValue = convertToNumeric(source);
            if (numericValue == null) {
                return null;
            }

            // 从数字转换为目标类型
            return convertFromNumeric(numericValue, targetType);
            
        } catch (Exception e) {
            log.debug("数字中转转换失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 转换为数字
     */
    private Double convertToNumeric(Object source) {
        try {
            if (source instanceof Number) {
                return ((Number) source).doubleValue();
            } else if (source instanceof String) {
                String str = ((String) source).trim();
                if (!str.isEmpty()) {
                    return Double.valueOf(str);
                }
            } else if (source instanceof Boolean) {
                return ((Boolean) source) ? 1.0 : 0.0;
            } else if (source instanceof Character) {
                return (double) (Character) source;
            }
        } catch (Exception e) {
            log.debug("转换为数字失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 从数字转换
     */
    @SuppressWarnings("unchecked")
    private <T> T convertFromNumeric(Double numericValue, Class<T> targetType) {
        try {
            if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf(numericValue.intValue());
            } else if (targetType == Long.class || targetType == long.class) {
                return (T) Long.valueOf(numericValue.longValue());
            } else if (targetType == Double.class || targetType == double.class) {
                return (T) numericValue;
            } else if (targetType == Float.class || targetType == float.class) {
                return (T) Float.valueOf(numericValue.floatValue());
            } else if (targetType == Short.class || targetType == short.class) {
                return (T) Short.valueOf(numericValue.shortValue());
            } else if (targetType == Byte.class || targetType == byte.class) {
                return (T) Byte.valueOf(numericValue.byteValue());
            } else if (targetType == Boolean.class || targetType == boolean.class) {
                return (T) Boolean.valueOf(numericValue != 0);
            } else if (targetType == String.class) {
                return (T) numericValue.toString();
            }
        } catch (Exception e) {
            log.debug("从数字转换失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 尝试集合转换
     */
    @SuppressWarnings("unchecked")
    private <T> T tryCollectionConversion(Object source, Class<T> targetType, T defaultValue) {
        try {
            if (source == null) {
                return null;
            }

            // 目标类型是否为集合
            if (Collection.class.isAssignableFrom(targetType)) {
                return (T) convertToCollection(source, targetType);
            }
            
            // 源对象是否为集合
            if (source instanceof Collection) {
                Collection<?> sourceCollection = (Collection<?>) source;
                if (!sourceCollection.isEmpty()) {
                    // 取第一个元素进行转换
                    Object firstElement = sourceCollection.iterator().next();
                    return tryMultipleConversions(null, firstElement, targetType, defaultValue, null);
                }
            }
            
        } catch (Exception e) {
            log.debug("集合转换失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 转换为集合
     */
    @SuppressWarnings("unchecked")
    private <T> Collection<T> convertToCollection(Object source, Class<T> targetType) {
        try {
            Collection<T> result;
            
            // 创建合适的集合实例
            if (List.class.isAssignableFrom(targetType)) {
                result = new ArrayList<>();
            } else if (Set.class.isAssignableFrom(targetType)) {
                result = new HashSet<>();
            } else {
                result = new ArrayList<>();
            }
            
            // 如果源是集合，复制元素
            if (source instanceof Collection) {
                for (Object item : (Collection<?>) source) {
                    result.add((T) item);
                }
            } else if (source.getClass().isArray()) {
                // 如果源是数组，转换数组元素
                int length = Array.getLength(source);
                for (int i = 0; i < length; i++) {
                    result.add((T) Array.get(source, i));
                }
            } else {
                // 单个元素转换为单元素集合
                result.add((T) source);
            }
            
            return result;
            
        } catch (Exception e) {
            log.debug("转换为集合失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 尝试数组转换
     */
    @SuppressWarnings("unchecked")
    private <T> T tryArrayConversion(Object source, Class<T> targetType, T defaultValue) {
        try {
            if (source == null) {
                return null;
            }

            // 目标类型是否为数组
            if (targetType.isArray()) {
                return (T) convertToArray(source, targetType.getComponentType());
            }
            
            // 源对象是否为数组
            if (source.getClass().isArray()) {
                int length = Array.getLength(source);
                if (length > 0) {
                    // 取第一个元素进行转换
                    Object firstElement = Array.get(source, 0);
                    return tryMultipleConversions(null, firstElement, targetType, defaultValue, null);
                }
            }
            
        } catch (Exception e) {
            log.debug("数组转换失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 转换为数组
     */
    @SuppressWarnings("unchecked")
    private <T> T[] convertToArray(Object source, Class<T> componentType) {
        try {
            if (source instanceof Collection) {
                Collection<?> sourceCollection = (Collection<?>) source;
                T[] result = (T[]) Array.newInstance(componentType, sourceCollection.size());
                
                int i = 0;
                for (Object item : sourceCollection) {
                    Array.set(result, i++, item);
                }
                
                return result;
            } else if (source.getClass().isArray()) {
                int length = Array.getLength(source);
                T[] result = (T[]) Array.newInstance(componentType, length);
                
                for (int i = 0; i < length; i++) {
                    Array.set(result, i, Array.get(source, i));
                }
                
                return result;
            } else {
                // 单个元素转换为单元素数组
                T[] result = (T[]) Array.newInstance(componentType, 1);
                Array.set(result, 0, source);
                return result;
            }
        } catch (Exception e) {
            log.debug("转换为数组失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 尝试自定义兼容转换
     */
    @SuppressWarnings("unchecked")
    private <T> T tryCustomCompatibleConversion(Object source, Class<T> targetType, T defaultValue) {
        try {
            if (source == null) {
                return null;
            }

            // 特殊的兼容转换规则
            
            // 枚举转换
            if (targetType.isEnum()) {
                return convertToEnum(source, targetType);
            }
            
            // 日期时间转换（简单处理）
            if (targetType == java.util.Date.class || 
                targetType == java.sql.Date.class ||
                targetType == java.sql.Timestamp.class) {
                return convertToDate(source, targetType);
            }
            
            // 对象到Map的转换
            if (targetType == Map.class && source != null) {
                return (T) convertObjectToMap(source);
            }
            
            // Map到对象的转换（简单处理）
            if (source instanceof Map && !targetType.isPrimitive() && 
                !Number.class.isAssignableFrom(targetType) && 
                targetType != String.class) {
                return convertMapToObject((Map<?, ?>) source, targetType);
            }
            
        } catch (Exception e) {
            log.debug("自定义兼容转换失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 转换为枚举
     */
    @SuppressWarnings("unchecked")
    private <T> T convertToEnum(Object source, Class<T> enumType) {
        try {
            if (source instanceof String) {
                String enumName = ((String) source).trim();
                for (T enumConstant : enumType.getEnumConstants()) {
                    if (enumConstant.toString().equalsIgnoreCase(enumName)) {
                        return enumConstant;
                    }
                }
            } else if (source instanceof Number) {
                int ordinal = ((Number) source).intValue();
                T[] enumConstants = enumType.getEnumConstants();
                if (ordinal >= 0 && ordinal < enumConstants.length) {
                    return enumConstants[ordinal];
                }
            }
        } catch (Exception e) {
            log.debug("转换为枚举失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 转换为日期
     */
    @SuppressWarnings("unchecked")
    private <T> T convertToDate(Object source, Class<T> dateType) {
        try {
            if (source instanceof Long) {
                long timestamp = (Long) source;
                if (dateType == java.util.Date.class) {
                    return (T) new java.util.Date(timestamp);
                } else if (dateType == java.sql.Date.class) {
                    return (T) new java.sql.Date(timestamp);
                } else if (dateType == java.sql.Timestamp.class) {
                    return (T) new java.sql.Timestamp(timestamp);
                }
            } else if (source instanceof String) {
                String strValue = ((String) source).trim();
                long timestamp = Long.parseLong(strValue);
                if (dateType == java.util.Date.class) {
                    return (T) new java.util.Date(timestamp);
                } else if (dateType == java.sql.Date.class) {
                    return (T) new java.sql.Date(timestamp);
                } else if (dateType == java.sql.Timestamp.class) {
                    return (T) new java.sql.Timestamp(timestamp);
                }
            }
        } catch (Exception e) {
            log.debug("转换为日期失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 将对象转换为Map
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> convertObjectToMap(Object source) {
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 简单处理：使用toString作为值
            result.put("value", source.toString());
            result.put("class", source.getClass().getName());
            
            return result;
        } catch (Exception e) {
            log.debug("转换为Map失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 将Map转换为对象
     */
    @SuppressWarnings("unchecked")
    private <T> T convertMapToObject(Map<?, ?> sourceMap, Class<T> targetType) {
        try {
            // 简单处理：尝试从Map中获取value字段
            Object value = sourceMap.get("value");
            if (value != null) {
                return tryMultipleConversions(null, value, targetType, null, null);
            }
        } catch (Exception e) {
            log.debug("从Map转换对象失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 检查是否为默认值
     */
    private <T> boolean isDefaultValue(T result, T defaultValue) {
        if (result == null && defaultValue == null) {
            return true;
        }
        return Objects.equals(result, defaultValue);
    }

    @Override
    public ConversionStrategyEnum getName() {
        return ConversionStrategyEnum.COMPATIBLE;
    }

    @Override
    public String getDescription() {
        return "兼容模式转换策略，最大程度兼容各种类型转换，包括复杂的类型转换场景，实现多级回退机制";
    }

    @Override
    public boolean supports(ConversionContext context) {
        return context != null && context.getStrategy().isCompatible();
    }
}
